﻿
using System;
using SanguoSharp.Server.Cards;
namespace SanguoSharp.Server
{
    public class Card : ImmortalMarshalByRefObject, ICard
    {
        private sealed class EmptyCard : ImmortalMarshalByRefObject, ICard
        {
            private int id;

            public int ID
            {
                get { return id; }
            }
            public CardColor Color
            {
                get { return CardColor.Unknown; }
            }
            public CardType Type
            {
                get { return CardType.Unknown; }
            }
            public CardSuit Suit
            {
                get { return CardSuit.Unknown; }
            }
            public CardRank Rank
            {
                get { return CardRank.Unknown; }
            }

            public EmptyCard(Card parent)
            {
                this.id = parent.id;
            }
        }
        private Game game;
        private int id;
        private CardColor color;
        private CardType type;
        private CardSuit suit;
        private CardRank rank;
        private Player owner;
        private EmptyCard empty;

        public Game Game
        {
            get { return game; }
        }
        public int ID
        {
            get { return id; }
        }
        public CardColor Color
        {
            get { return color; }
        }
        public CardType Type
        {
            get { return type; }
        }
        public CardSuit Suit
        {
            get { return suit; }
        }
        public CardRank Rank
        {
            get { return rank; }
        }
        public Player Owner
        {
            get { return owner; }
            set { owner = value; }
        }
        public bool IsInHand
        {
            get { return owner == null ? false : owner.Hand.Contains(this); }
        }
        public bool IsOnTable
        {
            get { return owner == null ? false : owner.Table.Contains(this as TableCard); }
        }
        public bool IsWeapon
        {
            get
            {
                switch (type)
                {
                    case CardType.雌雄双股剑:
                    case CardType.方天画戟:
                    case CardType.古锭刀:
                    case CardType.贯石斧:
                    case CardType.寒冰剑:
                    case CardType.麒麟弓:
                    case CardType.青釭剑:
                    case CardType.青龙偃月刀:
                    case CardType.丈八蛇矛:
                    case CardType.朱雀羽扇:
                    case CardType.诸葛连弩:
                        return true;
                }
                return false;
            }
        }

        public virtual int WeaponRange
        {
            get { return 1; }
        }
        public virtual bool UnlimitedBangs
        {
            get { return false; }
        }
        public virtual int DistanceIn
        {
            get { return 0; }
        }
        public virtual int DistanceOut
        {
            get { return 0; }
        }

        public ICard Empty
        {
            get { return empty; }
        }

        protected Card(Game game, int id, CardType type, CardSuit suit, CardRank rank)
        {
            this.game = game;
            this.id = id;
            this.type = type;
            this.suit = suit;
            this.rank = rank;
            color = GetColor(type);
            empty = new EmptyCard(this);
        }

        public override void Disconnect()
        {
            base.Disconnect();
            empty.Disconnect();
        }

        public void AssertInHand()
        {
            if (owner == null)
                throw new BadCardException();
            if (!owner.Hand.Contains(this))
                throw new BadCardException();
        }

        /// <summary>
        /// 检测是否装备上
        /// </summary>
        public void AssertOnTable()
        {
            if (Owner == null)
                throw new BadCardException();
            if (!Owner.Table.Contains(this as TableCard))
                throw new BadCardException();
        }

        public virtual void CheckMissed(CardResultMethod resultMethod)
        {
            throw new BadCardException();
        }
        public virtual void Play()
        {
            throw new BadUsageException();
        }
        public virtual void PlayVirtually(Card card)
        {
            throw new BadUsageException();
        }

        private static CardColor GetColor(CardType type)
        {
            switch (type)
            {
                case CardType.火杀:
                case CardType.酒:
                case CardType.雷杀:
                case CardType.杀:
                case CardType.闪:
                case CardType.桃:
                    return CardColor.基本牌;
                case CardType.八卦阵:
                case CardType.白银狮子:
                case CardType.赤兔:
                case CardType.大宛:
                case CardType.的卢:
                case CardType.绝影:
                case CardType.仁王盾:
                case CardType.藤甲:
                case CardType.爪黄飞电:
                case CardType.紫骍:
                    return CardColor.装备牌;
                case CardType.兵粮寸断:
                case CardType.过河拆桥:
                case CardType.决斗:
                case CardType.乐不思蜀:
                case CardType.南蛮入侵:
                case CardType.顺手牵羊:
                case CardType.桃园结义:
                case CardType.铁索连环:
                case CardType.万箭齐发:
                case CardType.无懈可击:
                case CardType.无中生有:
                case CardType.五谷丰登:
                    return CardColor.锦囊牌;
                //case CardType.:
                default:
                    return CardColor.Unknown;
            }
        }
        public static Card GetCard(Game game, int id, CardType type, CardSuit suit, CardRank rank)
        {
            switch (type)
            {
                case CardType.杀:
                    return new Cards.杀(game, id, suit, rank);
                case CardType.闪:
                    return new 闪(game, id, suit, rank);
                case CardType.桃:
                    return new 桃(game, id, suit, rank);
                case CardType.无中生有:
                    return new 无中生有(game, id, suit, rank);
                case CardType.五谷丰登:
                    return new 五谷丰登(game, id, suit, rank);
                case CardType.顺手牵羊:
                    return new 顺手牵羊(game, id, suit, rank);
                case CardType.过河拆桥:
                    return new 过河拆桥(game, id, suit, rank);
                case CardType.南蛮入侵:
                    return new 南蛮入侵(game, id, suit, rank);
                case CardType.万箭齐发:
                    return new 万箭齐发(game, id, suit, rank);
                case CardType.决斗:
                    return new 决斗(game, id, suit, rank);;
                case CardType.赤兔:
                    return new 赤兔(game, id, suit, rank);
                case CardType.诸葛连弩:
                    return new 诸葛连弩(game, id, suit, rank);
                case CardType.八卦阵:
                    return new 八卦阵(game, id, suit, rank);
                case CardType.闪电:
                    return new 闪电(game, id, suit, rank);
                case CardType.乐不思蜀:
                    return new 乐不思蜀(game, id, suit, rank);
                case CardType.丈八蛇矛:
                    return new 丈八蛇矛(game, id, suit, rank);
                case CardType.寒冰剑:
                    return new 寒冰剑(game, id, suit, rank);
                case CardType.桃园结义:
                    return new 桃园结义(game, id, suit, rank);
                case CardType.绝影:
                    return new 绝影(game, id, suit, rank);
                case CardType.麒麟弓:
                    return new 麒麟弓(game, id, suit, rank);
                case CardType.方天画戟:
                    return new 方天画戟(game, id, suit, rank);
                //case CardType.: return new(game, id, suit, rank);
                default:
                    throw new ArgumentOutOfRangeException("type");
            }
        }
    }
}
